#ifndef NETWORK_BYTEARRAY_H
#define NETWORK_BYTEARRAY_H

#include <cstdlib>
#include <cstdio>
#include <stdexcept>
#include <vector>
#include <string>
#include <cstring>

#include "ArgumentException.hpp"


namespace Network
{
	//! Classe permettant de créer et de manipuler un tableau de bytes
	class ByteArray
	{
		private:
		
		int					_capacity;
		int					_size;
		void*				_data;
		
		
		public:
		
		//! Constructeur de tableau de bytes. 
		ByteArray();
		
		//! Constructeur de tableau de bytes. 
		ByteArray(int n);
		
		//! Constructeur de tableau de bytes. 
		ByteArray(int n, char value);
		
		//! Constructeur de tableau de bytes. 
		//! Construit un buffer contenant un seul caractère.
		ByteArray(char data);
		
		//! Constructeur de tableau de bytes. 
		ByteArray(const void* data, int len);
		
		//! Constructeur de tableau de bytes. 
		//! Contruit le tableau en utilisant la méthode fromCString. 
		//! Attention, on ne peut pas utiliser ce constructeur pour 
		//! rechercher le caractère '\0' ou des chaines qui le contient.
		ByteArray(const char* data);
		
		//! Constructeur de tableau de bytes. 
		//! Contruit le tableau en utilisant la méthode fromString. 
		//! Attention, on ne peut pas utiliser ce constructeur pour 
		//! rechercher le caractère '\0' ou des chaines qui le contient.
		ByteArray(const std::string& data);
		
		//! Constructeur de tableau de bytes. 
		//! Contruit le tableau en utilisant la méthode fromVector. 
		ByteArray(const std::vector<char>& data);
		
		//! Constructeur de copie de tableau de bytes. 
		ByteArray(const ByteArray& data);
		
		//! Destructeur de tableau de bytes. 
		virtual ~ByteArray();
		
		//! Redimentionne le tableau dynamique
		void resize(int size) throw(ArgumentException);
		
		//! Redimentionne le tableau dynamique. 
		//! Si la nouvelle taille est plus grande que l'ancienne, 
		//! les valeurs ajoutées prennent la valeur de 'value'. 
		void resize(int size, char value) throw(ArgumentException);
		
		//! Permet de connaitre la taille du tableau dynamique. 
		//! Cette méthode est identique à la méthode size. 
		int count() const;
		
		//! Compte le nombre d'occurences d'un byte dans le tableau de bytes. 
		int count(char byte, int from = 0) const;
		
		//! Compte le nombre d'occurences d'un sous-tableau 
		//! dans le tableau de bytes. 
		int count(const ByteArray& ba, int from = 0) const;
		
		//! Recherche un byte dans le tableau de bytes. 
		int find(char byte, int from = 0) const;
		
		//! Recherche un sous-tableau dans le tableau de bytes. 
		int find(const ByteArray& ba, int from = 0) const;
		
		//! Permet de connaitre la taille du tableau dynamique. 
		//! Cette méthode est identique à la méthode count. 
		int size() const;
		
		//! Permet de connaitre la capacité du tableau dynamique. 
		//! La capacité du tableau est la taille réel allouée pour stocker 
		//! les données. <br />
		//! Remarque : l'égallité suivante est toujours respecté : <br />
		//! capacity()/2 < size() <= capacity()
		int capacity() const;
		
		//! Permet de savoir si le tableau de byte est vide ou non. 
		//! Le tableau est vide si et seulement si la taille est nulle. 
		bool empty() const;
		
		//! 
		ByteArray left(int length) const;
		
		//! 
		ByteArray right(int length) const;
		
		//! 
		ByteArray mid(int from, int length) const;
		
		//! Permet de définir un tableau de bytes à partir d'une chaine de 
		//! caractères de type C (le \0 terminal n'est pas copié). 
		//! @param data Chaine de caractères à convertir
		//! Attention, on ne peut pas utiliser cette méthode pour 
		//! rechercher le caractère '\0' ou des chaines qui le contient.
		void fromCString(const char* data);
		
		//! Permet de définir un tableau de bytes à partir d'une chaine de 
		//! caractères (le \0 terminal n'est pas copié). 
		//! @param data Chaine de caractères à convertir
		//! Attention, on ne peut pas utiliser cette méthode pour 
		//! rechercher le caractère '\0' ou des chaines qui le contient.
		void fromString(const std::string& data);
		
		//! Permet de définir un tableau de bytes à partir d'un vecteur. 
		//! @param data Vecteur à convertir
		void fromVector(const std::vector<char>& data);
		
		//! Permet de convertir un tableau de bytes en chaine de caractères. 
		//! @return Chaine de caractères convertie. 
		std::string toString() const;
		
		//! Permet de convertir un tableau de bytes en vecteur. 
		//! @return Vecteur convertie. 
		std::vector<char> toVector() const;
		
		bool operator==(const ByteArray& other) const;
		bool operator!=(const ByteArray& other) const;
		ByteArray& operator+=(const ByteArray& other);
		ByteArray& operator=(const ByteArray& other);
		char& operator[](int index);
		const char& operator[](int index) const;
		
		
		private:
		
		//! Permet de trouver la puissance de deux supérieure ou 
		//! égale à un nombre.
		//! @param n Nombre dont on veut trouver la puissance de deux 
		//!          supérieure ou égale.
		//! @return Puissance de deux supérieure ou égale à n
		unsigned int pow2ge(unsigned int n);
		
		
		friend ByteArray operator+(const ByteArray& ba1, const ByteArray& ba2);
	};
}


#endif


